package com.caijb.juc;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.*;

/**
 * 关键特性
 * 可重用性：CyclicBarrier 可以被多次使用
 * 回调机制：支持在所有线程到达屏障时执行回调方法
 * 异常处理：当线程被中断时会抛出 BrokenBarrierException
 * 使用场景
 * 多线程计算数据，最后合并计算结果
 * 多线程处理不同部分的数据，需要等待所有部分完成再继续
 * 并行任务的阶段性同步
 * @author caijb
 * @version 1.0
 * @data 2025/10/31 00:28
 */
public class CyclicBarrierDemo {
    public static void main(String[] args) {
        runningGame();
//        demo();
    }

    @Data
    @AllArgsConstructor
    static class Student {
        private String name;
        private int score;
        private int sort;
    }

    private static void runningGame() {
        CopyOnWriteArrayList<Student> students = new CopyOnWriteArrayList<>();
        CyclicBarrier barrier = new CyclicBarrier(5, () -> {
            // 当所有线程都到达屏障时执行的回调
            calculateRanking(students);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        for (int i = 1; i <= 5; i++) {
            int finalI = i;
            new Thread(() -> {
                students.add(new Student("学生" + finalI, ThreadLocalRandom.current().nextInt(1, 101),0));
                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }
                students.stream()
                        .filter(student -> student.getName().equals("学生" + finalI))
                        .findFirst()
                        .ifPresent(student ->
                                System.out.println("学生" + finalI + "的排名为：" + student.getSort() + "，成绩为：" + student.getScore())
                        );
            }).start();
        }
    }

    /**
     * 根据得分计算排名并设置到sort属性
     * @param list 包含得分和sort属性的对象列表
     */
    public static void calculateRanking(List<Student> list) {
        // 1. 按照得分降序排列
        Collections.sort(list, Comparator.comparing(Student::getScore).reversed());

        // 2. 设置排名
        int rank = 1;
        int sameScoreCount = 0;

        for (int i = 0; i < list.size(); i++) {
            Student current = list.get(i);

            if (i > 0 && current.getScore() == list.get(i - 1).getScore()) {
                // 得分相同，排名相同
                sameScoreCount++;
                current.setSort(rank);
            } else {
                // 得分不同，更新排名
                rank = i + 1;
                current.setSort(rank);
                sameScoreCount = 0;
            }
        }
    }

    private static void demo() {
        // 创建一个CyclicBarrier，需要3个线程到达屏障
        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            // 当所有线程都到达屏障时执行的回调
            System.out.println("所有线程都到达屏障点，开始下一步操作！");
        });

        // 创建并启动3个线程
        for (int i = 1; i <= 3; i++) {
            final int threadId = i;
            new Thread(() -> {
                try {
                    System.out.println("线程 " + threadId + " 开始执行任务...");
                    // 模拟不同的执行时间
                    Thread.sleep(threadId * 1000);

                    System.out.println("线程 " + threadId + " 完成第一阶段任务，等待其他线程...");
                    // 等待其他线程到达屏障点
                    barrier.await();

                    System.out.println("线程 " + threadId + " 继续执行第二阶段任务...");
                    Thread.sleep(1000);

                    System.out.println("线程 " + threadId + " 完成所有任务！");
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }, "Thread-" + i).start();
        }
    }
}
